package jxtcpclient

import (
	"context"
	"fmt"
	"sync"
	"time"
)

type Pool struct {
	Address           string
	MacthineId        uint32
	clientCount       int
	list              []*Conn
	onMessage         func(*Message)
	onClose           func(error)
	onProgress        func(*Progress)
	SendOver          int
	OverTime          int
	sendMessageReturn sync.Map
	sendMessageMsg    sync.Map
}

func (p *Pool) init() {
	for i := 0; i < p.clientCount; i++ {
		val := NewConn(p.Address, p.MacthineId, p.onMessage, p.onClose)
		p.list = append(p.list, val)
	}
}
func (p *Pool) SetSendOver(t int) {
	p.SendOver = t
}
func (p *Pool) SetOverTime(t int) {
	p.OverTime = t
}
func (p *Pool) SetOnProgress(f func(*Progress)) {
	p.onProgress = f
}
func NewPool(address string, machineid uint32, maxcount int, onmessage func(*Message), onclose func(error), overtime ...int) *Pool {

	outdata := &Pool{
		Address:     address,
		clientCount: maxcount,
		list:        make([]*Conn, 0),
		onClose:     onclose,
		MacthineId:  machineid,
		OverTime:    10,
		SendOver:    10,
	}
	onm := func(m *Message) {
		if m.Type == 0 {
			msg, ok := outdata.sendMessageReturn.Load(m.Id)
			if ok {
				ch, ok := msg.(chan *Message)
				if ok {
					ch <- m
				}
			}
		} else {
			msg, ok := outdata.sendMessageMsg.Load(m.Id)
			if ok {
				ch, ok := msg.(chan *Message)
				if ok {
					ch <- m
				}
			}
		}
		if onmessage != nil {
			onmessage(m)
		}
	}
	outdata.onMessage = onm
	outdata.init()
	return outdata
}
func (p *Pool) Close() {
	for _, val := range p.list {
		val.Stop()
	}
}
func (p *Pool) SendMessage(m *Message, f ...func(*Message)) (*Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(p.SendOver))
	defer func() {
		cancel()
	}()
	returnmsg := make(chan *Message)
	msgchan := make(chan *Message, 5)
	p.sendMessageReturn.Store(m.Id, returnmsg)
	p.sendMessageMsg.Store(m.Id, msgchan)
	defer func() {
		p.sendMessageReturn.Delete(m.Id)
		p.sendMessageMsg.Delete(m.Id)
		close(msgchan)
		close(returnmsg)
	}()

sendmessage:
	for {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("客户端发送消息超时:%v", p.SendOver)
		default:
			for _, val := range p.list {
				err := val.SendMessage(m)
				if err == nil {
					break sendmessage
				}
			}
			time.Sleep(time.Millisecond * time.Duration(GetRandInt(50, 100)))
		}
	}
	ctxread, cancelread := context.WithTimeout(context.Background(), time.Second*time.Duration(p.OverTime))
	defer cancelread()
	for {
		select {
		case msg := <-msgchan:
			if len(f) > 0 {
				f[0](msg)
			}
		case <-ctxread.Done():
			return nil, fmt.Errorf("获得处理结果超时")
		case msg := <-returnmsg:
			return msg, nil
		}
	}
}
